package ppjava12v1.chess.dao.hibernate;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;
import ppjava12v1.chess.dao.UserDAO;
import ppjava12v1.chess.entities.users.User;
import ppjava12v1.chess.entities.users.UserProfile;
import ppjava12v1.chess.entities.users.UserRole;
import ppjava12v1.chess.enums.Role;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by Reyst on 21.09.2014.
 *
 */
@Repository
public class HibernateUserDAO implements UserDAO {

    @Resource(name = "sessionFactory")
    SessionFactory factory;

    private Session getSession(){
        Session session = null;
        try {
            session = factory.getCurrentSession();
        } catch (HibernateException ex) {
            session = factory.openSession();
        }

        if (session == null)
            session = factory.openSession();

        return session;
    }


    @Override
    public User getByLogin(String login) {
        Session s = getSession();

        // Получили пользователя по логину (электронной почте)
        User user = (User) s.createQuery("from User where login = :login")
                .setParameter("login", login)
                .uniqueResult();

        if (user != null){

            // Подтягиваем его роли
            List usrRoles = s.createQuery("Select ur.role From UserRole ur where ur.user = :user")
                    .setParameter("user", user)
                    .list();
            Set<Role> roles = new HashSet<>();

            for (Object usrRole : usrRoles) {
                if (usrRole instanceof Role)
                    roles.add((Role)usrRole);
            }
            user.setRoles(roles);

        }

        return user;
    }

    @Override
    public String saveUser(User user) {

        Session s = getSession();

        Transaction tx = s.beginTransaction();

        try{

            // Сохранили юзера
            s.saveOrUpdate(user);

            // сохранили/обновили профайл юзера
            updateProfile(user.getProfile());

            // удаляем все записи о ролях пользователя и создаем новые
            // Сам пользователь меняться практически не будет,
            // поэтому можно повесить и долгую операцию
            // опять же, роли пользователя тоже могут измениться только в экстраординарном случае
//        s.createQuery("delete from UserRole where user = :user")
//                .setParameter("user", user)
//                .executeUpdate();

            Set<Role> roles = user.getRoles();
            for (Role role : roles)
                s.saveOrUpdate(new UserRole(user,role));

        }  catch (Exception ignore){

            System.out.println(ignore.toString());

            return "This name already exists";

        }

        tx.commit();

        return "Success";
    }

    @Override
    public void updateProfile(UserProfile profile) {
        Session s = getSession();
        s.saveOrUpdate(profile);
    }

    @Override
    public int getRaiting(User user) {

        // TODO: Написать алгоритм расчета рейтинга

        return 0;
    }
}
